package com.qiguliuxing.dts.core.annotation.repeat;

import com.qiguliuxing.dts.common.util.ResponseUtils;
import com.qiguliuxing.dts.core.redis.RedisServiceUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.UUID;

/**
 * 防止订单重复提交
 */
@Slf4j
@Aspect
@Component
public class RepeatSubmitAspect {


    @Pointcut("@annotation(noRepeatSubmit)")
    public void pointcut(NoRepeatSubmit noRepeatSubmit) {}

    @Around("pointcut(noRepeatSubmit)")
    public Object around(ProceedingJoinPoint pjp, NoRepeatSubmit noRepeatSubmit) throws Throwable {
        int lockSeconds = noRepeatSubmit.lockTime();
        ServletRequestAttributes ra= (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = ra.getRequest();
        Assert.notNull(request, "request can not null");
        String token = request.getHeader("X-Dts-Token");
        if(StringUtils.isBlank(token)){
            token = request.getHeader("fingerprint");
        }
        String path = request.getServletPath();
        String key = getKey(token, path);
        String clientId = getClientId();
        boolean isSuccess = RedisServiceUtil.tryLock(key, clientId, lockSeconds);
        log.info("tryLock key = [{}], clientId = [{}]", key, clientId);
        if (isSuccess) {
            // 获取锁成功
            Object result;
            // 执行进程
            result = pjp.proceed();
            return result;
        } else {
            // 获取锁失败，认为是重复提交的请求，返回
            log.info("tryLock fail, key = [{}]", key);
            return ResponseUtils.fail(303,"重复请求，请稍后再试");
        }
    }

    private String getKey(String token, String path) {
        return token + path;
    }

    private String getClientId() {
        return UUID.randomUUID().toString();
    }

}
